package com.yuw.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;

public class MyUtils {

	/**
	 * 使用反射，将request中提交的form表单数据映射到实体类中 约定：表达的name属性值和数据库的字段名保持一致【大小写敏感】
	 * 
	 * @param request request请求对象
	 * @param clazz   实体类的Class
	 * @return 映射表达数据的实体类实例
	 */
	public static <T> T convertFormData2Bean(HttpServletRequest request, Class<T> clazz) {
		T t = getInstance(clazz);
		if (request != null) {

			/*******
			 * 注册定义了类型转换器：form表单中的String串向目标数据类型的自定义转换 
			 * 定义BeanUtils的包装类类型的转换器【可以使用匿名内部类】
			 ********/
			ConvertUtils.register(new DateTimeConverter(), Date.class);

			// 获取request中提交所有的表单控件的name属性值
			Enumeration<String> paramNames = request.getParameterNames();
			if (paramNames != null) {
				// 遍历每一个元素
				try {
					while (paramNames.hasMoreElements()) {
						// 取出当前遍历的元素对象:当前的表单的name属性值
						String strName = paramNames.nextElement();
						// 从request获取当前form表单的name属性对应的value值
						String strVal = request.getParameter(strName);
						// 使用反射将表单的value值设置到与之对应的实体类属性中【借助beanutils或者直接使用反射】
						BeanUtils.setProperty(t, strName, strVal);
					}
				} catch (Exception e) {
					// form表单属性值映射到实体类中异常：
					System.out.println("form表单属性值映射到实体类中异常：" + e.getMessage());
					e.printStackTrace();
				}
			}
		}
		return t;
	}

	/**
	 * 将时间类型专为制定格式的字符串【转换失败返回null】
	 * 
	 * @param date           被转化的时间对象
	 * @param strDatePattern 转换的时间格式串
	 * @return 转换之后的日期字符串
	 */
	public static String convertDate2String(Date date, String strDatePattern) {
		// 返回值
		String strDate = null;

		// 日期格式串检测
		if (strDatePattern == null || strDatePattern.equals("")) {
			// 给定默认的时间格式串
			strDatePattern = "yyyy-MM-dd HH:mm:ss";
		}

		// 创建日期转换类
		SimpleDateFormat sdf = new SimpleDateFormat(strDatePattern);

		if (date != null) {
			// 将日期类型专为指定格式的字符串
			strDate = sdf.format(date);
		} else {
			// 根据需求确定
			// strDate = sdf.format(new Date());
		}
		// 返回值
		return strDate;
	}

	/**
	 * 将字符串转换为日期对象 【注意：日期格式串和日期字符串要在格式上匹配】
	 * 
	 * @param strDate        日期字符串
	 * @param strDatePattern 日期格式串
	 * @return 转换之后的日期对象【默认为当前系统时间】
	 */
	public static Date convertString2Date(String strDate, String strDatePattern) {
		// 返回值，默认为当前时间【还是为null，根据业务需求定】
		Date date = new Date();
		// 日期格式串检测:注意：日期格式串和日期字符串要在格式上匹配
		if (strDatePattern == null || strDatePattern.equals("")) {
			// 给定默认的时间格式串
			strDatePattern = "yyyy-MM-dd HH:mm:ss";
		}

		// 创建日期转换类
		SimpleDateFormat sdf = new SimpleDateFormat(strDatePattern);

		try {
			// 进行日期转换
			date = sdf.parse(strDate);
		} catch (ParseException e) {
			// 日期转换异常
			System.out.println("字符串转为日期对象异常：" + e.getMessage());
			e.printStackTrace();
		}
		// 返回值
		return date;
	}

	/**
	 * 简单工厂模式：获取一个指定Class的实例对象
	 * 
	 * @param clazz Class
	 * @return 实例对象
	 */
	public static <T> T getInstance(Class<T> clazz) {
		// 返回值
		T t = null;
		try {
			// 反射获取该Class的一个实例对象
			t = clazz.newInstance();
		} catch (Exception e) {
			// 获取实例对象异常
			System.out.println("获取实例对象异常:" + e.getMessage());
			e.printStackTrace();
		}
		return t;
	}
}
